package org.ala.tiktools.rpc.kcp.protocol.sender.queue;

import org.ala.tiktools.rpc.kcp.protocol.IKcpSenderQueue;
import org.ala.tiktools.rpc.kcp.protocol.segment.KcpSegment;
import org.ala.tiktools.tools.queue.FixedCircularQueue;
import org.ala.tiktools.tools.queue.IQueueIterator;

/**
 *	循环数组实现
 *
 *	@author ala
 *	@date 2025年4月30日
 */
public class KcpSenderArrayQueue extends FixedCircularQueue<KcpSegment> implements IKcpSenderQueue {

	
	public KcpSenderArrayQueue(int capacity) {
		this(new KcpSegment[capacity]);
		//	在初始化时，就把对象准备好。避免频繁ygc
		for (int i = 0 ; i < capacity ; i++) {
			datas[i] = new KcpSegment();
		}
	}
	public KcpSenderArrayQueue(KcpSegment[] arr) {
		//	remove时不清除对象引用
		super(arr, false);
	}
	
	
	/**
	 * 	处理已经确认收到的una
	 * 	<p>	直接删小于una的
	 */
	@Override
	public int parseUna(long una) {
		IQueueIterator<KcpSegment> iterator = firstIterator();
		KcpSegment seg = null;
		int cnt = 0;
		while (iterator.hasNext() && (seg = iterator.current()).getSn() < una) {
			seg.recycle(true);
			cnt++;
			iterator.removeAndNext();
		}
		return cnt;
	}

	
	/**
     *  确认sn号
     *  <p>	删除sn号的seg
     *  <p>	队列中的sn号是升序的
     *  <p>	从头开始搜：O(n)
     *  <p>	实际场景中大概率消息是顺序过来的，没必要为了兼容抖动每次都log(n)
     */
	@Override
	public void parseAck(long sn) {
		IQueueIterator<KcpSegment> iterator = firstIterator();
		KcpSegment seg = null;
		while (iterator.hasNext() && (seg = iterator.current()).getSn() <= sn) {
			if (seg.getSn() == sn) {
				seg.recycle(true);
				iterator.removeAndNext();
				break;
			}
			iterator.next();
		}
	}

	
	/**
     *  处理fastack
     *  <p>	小于 ackSn 的seg，其fastAck自增一次
     *  <p>	如果遍历到了 > ackSn，不用遍历了
     *  <p> sndBuf中 < ackSn 的 消息，fastAck标记累加一次
     */
	@Override
	public void parseFastack(long ackSn) {
		IQueueIterator<KcpSegment> iterator = firstIterator();
		KcpSegment seg = null;
		while (iterator.hasNext() && (seg = iterator.current()).getSn() < ackSn) {
			seg.incrFastAck();
			iterator.next();
		}
	}
	
	
	@Override
	public void clear() {
		IQueueIterator<KcpSegment> iterator = firstIterator();
		KcpSegment seg = null;
		while (iterator.hasNext()) {
			seg = iterator.removeAndNext();
			seg.recycle(true);
		}
	}
	
}
